// Copyright (c) 2001 John Panzer
// Permission is granted to use this code without restriction as
// long as this copyright notice appears in all source files.
#ifndef __FIXED_STR_H_
#define __FIXED_STR_H_

#include <cassert>

#ifdef _DEBUG
#define xs_assert(x) assert(x)
#else
#define xs_assert(x)
#endif

#include "basictype.h"
#include <string.h>

// Fixed size character buffer class.

template <size_t SIZE> 
class fixed_char_buf {
public:
    // String interface typedefs:
    static const size_t npos;

	// Constructors:
	fixed_char_buf() {
		_end = _buffer;
	}

    // Constructors:
    fixed_char_buf(fixed_char_buf const &s) {
        memcpy(_buffer, s._buffer, SIZE+1);
		_end = _buffer + s.size();
    }

	// Constructors:
	fixed_char_buf(const char* s) {
		size_t len = strlen(s);
		if(len <= SIZE)
		{
			strcpy(_buffer, s);
			_end = _buffer + len;
		}
		else
			xs_assert(0&&"fixed_char_buf too short");
	}

    // Copy operator:
    fixed_char_buf &operator=(fixed_char_buf const &s) {
        if (this!=&s)
		{
            memcpy(_buffer, s._buffer, SIZE+1);
			_end = _buffer + s.size();;
		}
    }

	// == operator
	bool operator == (fixed_char_buf const &s) const
	{
		if(this==&s)
			return true;
		if(size() != s.size())
			return false;

		const char* p = _buffer;
		const char* q = s._buffer;
		for(; p < _end && q < s._end; ++p, ++q) {
			if(*p != *q)
				return false;
		}
		return true;
	}

    void clear() {_end = _buffer;}
    size_t max_size() const { return SIZE; }
    bool empty() const { return (_end == _buffer); }    
    size_t size() const {return _end - _buffer;}

    void swap(fixed_char_buf& s) {
        /// Not as cheap as some swaps, but guaranteed
        /// not to throw:
        for(int i=0;i<SIZE;++i) {
            s._buffer[i] ^= _buffer[i] ^= s._buffer[i] ^= _buffer[i];
        }
        int len = _end - _buffer;
        _end = s.size()+_buffer;
        s._end = len+s._buffer;
    }

    size_t capacity() const { return max_size(); }

    const char* c_str() const {
        *_end = 0; // Null terminate.
        return _buffer;
    }

    const char* data() const {
        return _buffer;
    }

private: 
    // A fixed size buffer implementation:
	char _buffer[SIZE+1]; // Space for SIZE elements + null 
    mutable char *_end;  // End of text in _buffer
};

/// Definition of "npos" constant:
template <size_t SIZE>
const size_t
      fixed_char_buf<SIZE>::npos 
      = (size_t) -1;

#endif
